-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RFC: Add no_entry
attribute to omit entry point symbol
#2735
Conversation
This allows people to write their own entry point, without needing to manually link or create a `.cargo/config` with target-specific linker arguments.
cc @retep998 As discussed on Discord, I added an explanation of the behavior on platforms that can't support
|
binary. When linking, Rust will pass any necessary target-specific arguments to | ||
the toolchain to omit the target's entry-point code, such as `-nostartfiles`. | ||
|
||
Binaries built with this attribute set will typically not link unless the user |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Elaborate on typically?
|
||
We could make this a rustc command-line option, rather than an attribute. | ||
However, that would separate the configuration required to build a crate from | ||
the crate itself. We have substantial precedent for including such |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe this is true but enumerate some examples nonetheless?
[future-possibilities]: #future-possibilities | ||
|
||
We should simplify the declaration of an entry-point symbol, such as by | ||
providing an `#[entry]` attribute. The symbol itself would still have a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we have #[entry]
on unsafe ... fn foobar(...)
do we then also need #![no_entry]
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FWIW this is an elaboration of https://github.com/rust-lang/rfcs/pull/2735/files/e4ad78dd444961bbc268f4f4a46189999750a5ca#r308998642
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Centril Yes, we do. entry
could be used in a library, for instance, with a binary crate using no_entry
and using that library. I'll add a note that it would make sense to have a lint if you use entry
in a binary crate without using no_entry
, though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@joshtriplett Ah I see; so this is akin to "needs / provides" of #![requires_allocator]
(because every program requires an entry point) and #[global_allocator]
. -- Please mention this similarity explicitly as well as the use-case for library/binary division in the text also. :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you mean by requires_allocator
? I don't see any references to that or similar names anywhere on the web.
The RFC already mentions the use case of library/binary division, in the rationale and alternatives section: "However, this would make it difficult to flexibly provide the entry point from a library or other mechanism."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you mean by
requires_allocator
? I don't see any references to that or similar names anywhere on the web.
Ooops; It's called #![needs_allocator]
in https://github.com/rust-lang/rust/blob/master/src/liballoc/lib.rs#L65 apparently.
The RFC already mentions the use case of library/binary division, in the rationale and alternatives section: "However, this would make it difficult to flexibly provide the entry point from a library or other mechanism."
Yes, but connecting this to entry
and no_entry
is another matter, it would be helpful to clarify that this is what is referred to by that sentence.
My main objection to this RFC is that this attribute should be described as part of the target specification rather than as an attribute. All of the use cases that you described will run without any libc, and therefore will want to use a custom target rather than one of the existing targets. As I noted in my comment on the pre-RFC thread, you can already do what is proposed in this RFC by adding |
It would be really helpful for this RFC to describe of exactly what functions are called during program startup under each valid configuration of
Based on that list, I'd be curious to understand why it wouldn't be enough to just add an attribute that said "set #![no_start] and make (possibly extern) #[start] item the executable entry point". |
I commented on that in the pre-RFC thread: target specifications are unstable, and likely to remain so for the foreseeable future since they fundamentally depend on LLVM and LLVM internals. In addition, this would require specifying a custom target, and potentially building core/std for that target, which will again require nightly for the foreseeable future.
That does not describe my use cases. I intend to use this on existing linux targets as well, for instance.
What target json? I'm not looking to use this exclusively for custom targets, nor do I want to permanently require nightly. Target json is a strictly worse solution for many use cases than |
Point of clarification: On Darwin, executable startup used to follow a scheme similar to Linux, with a What, if anything, should |
(Current status: revising RFC based on feedback, will post new version that addresses comments.) |
@comex Can you still write binaries that don't use libc at all? (It sounds like you can't use libc without the entry-point code like Linux's |
@joshtriplett Are you still in the process of making revisions? |
@joshtriplett LC_MAIN is handled by dyld, which is actually separate from libc aka libSystem. However, separately from that, the linker forbids creating dynamically linked executables that don't link to libSystem:
On the other hand, I just checked, and it looks like it's still possible to create statically linked executables using This is not particularly useful, though, since libSystem's system call wrappers are the only supported/stable way to perform system calls; even Go switched from emitting static binaries to linking against libSystem |
symbols. | ||
|
||
Existing programming languages rely entirely on the toolchain for this | ||
functionality. Introducing `no_entry` makes it possible to gain control from |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you provide a minimal example of how C (e.g. using clang) handles this? Do C compilers offer compiler extensions to make this simpler ?
While I'm still interested in seeing this happen, this needs some redesign to address portability (and handle platforms where you can't use libc without its entry point). I'm going to close this for now, with an eye towards opening something new in the future if possible. |
I've played with So, to stabilize something along this lines, it seems like we should also make sure that rustc doesn't rely on external compiler-builtins. |
This allows people to write their own entry point, without needing to
manually link or create a
.cargo/config
with target-specific linkerarguments.